/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.fsq.portscan;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.net.*;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Map;
import java.util.Map.Entry;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

import com.fsq.portscan.Utils.DbUtils;
import com.fsq.portscan.Utils.IpUtils;
import com.fsq.portscan.Utils.MyCookieStore;
import com.fsq.portscan.model.Row;
import com.fsq.portscan.model.RowSerializable;
import javafx.application.Platform;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Hyperlink;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.FileChooser;
import javafx.stage.FileChooser.ExtensionFilter;
import javafx.stage.Modality;
import javafx.stage.Stage;

/**
 * @author root
 */
public class FXMLDocumentController implements Initializable {

    @FXML
    private Button id_newscan;
    @FXML
    private Button id_stop;
    @FXML
    private Button id_shrink;
    @FXML
    private TextField id_url;
    @FXML
    private TextField id_urlsuffix;
    @FXML
    private Button id_open;
    @FXML
    private Hyperlink id_help;
    @FXML
    private Label id_status;
    @FXML
    private TreeView<String> id_treeview;
    @FXML
    private TableView<Row> id_tableview;
    @FXML
    private TableColumn<?, ?> id_coladdress;
    @FXML
    private TableColumn<?, ?> id_colssl;
    @FXML
    private TableColumn<?, ?> id_colserver;
    @FXML
    private TableColumn<?, ?> id_coltitle;
    @FXML
    private TableColumn<?, ?> id_colstatuscode;
    @FXML
    private TableColumn<?, ?> id_colresponse;
    @FXML
    private TableColumn<?, ?> is_colcontentlength;
    @FXML
    private TableColumn<?, ?> id_colRealIp;
    @FXML
    private AnchorPane id_browserpane;
    @FXML
    private TextArea id_notepad;
    @FXML
    private TextArea id_serverinfo;
    @FXML
    private MenuItem id_expand;
    @FXML
    private MenuItem id_collapse;
    @FXML
    private MenuItem id_sendh;
    @FXML
    private MenuItem id_sendhp;
    @FXML
    private MenuItem id_sendhhp;
    @FXML
    private MenuItem id_sendallh;
    @FXML
    private MenuItem id_sendallhp;
    @FXML
    private MenuItem id_sendallhhp;

    @FXML
    private MenuItem id_openbrowser;

    @FXML
    private MenuItem id_exporttxt;
    @FXML
    private MenuItem id_sendhttp;
    @FXML
    private MenuItem id_sendhttps;
    @FXML
    private MenuItem id_exportdata;
    @FXML
    private MenuItem id_importdata;
    @FXML
    private MenuItem id_deleteitems;
    @FXML
    private MenuItem id_cleartableview;
    @FXML
    private CheckBox id_autodeleteempty;

    @FXML
    private MenuItem id_refresh;

    private WebView id_webview;

    private ExecutorService threadPool;
    private TreeItem<String> treeItem;
    private LinkedList<ScanTask> taskList = new LinkedList<ScanTask>();
    public static Integer taskCount;

    @Override
    public void initialize(URL url, ResourceBundle rb) {

        MyCookieStore myCookieStore = new MyCookieStore();

        // set cookie manager
        CookieManager manager = new CookieManager(myCookieStore, null);

        CookieHandler.setDefault(manager);


        // System.out.println(System.getenv());
        id_tableview.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
        taskCount = new Integer(0);
        // add root node of tree
        treeItem = new TreeItem<String>("+");
        id_treeview.setRoot(treeItem);

        // init tableview
        id_tableview.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
        id_coladdress.setCellValueFactory(new PropertyValueFactory<>("address"));
        id_colssl.setCellValueFactory(new PropertyValueFactory<>("ssl"));
        id_colserver.setCellValueFactory(new PropertyValueFactory<>("server"));
        id_coltitle.setCellValueFactory(new PropertyValueFactory<>("title"));
        id_colstatuscode.setCellValueFactory(new PropertyValueFactory<>("statuscode"));
        is_colcontentlength.setCellValueFactory(new PropertyValueFactory<>("contentLength"));
        id_colresponse.setCellValueFactory(new PropertyValueFactory<>("response"));
        id_colRealIp.setCellValueFactory(new PropertyValueFactory<>("realIp"));

        // init db
        DbUtils.init();

        // create table
        String sql1 = "DROP TABLE  IF EXISTS PUBLIC.webfinderplus;";
        String sql2 = "CREATE TABLE PUBLIC.webfinderplus(ADDRESS VARCHAR(100),SSL BOOLEAN,SERVER VARCHAR(200),TITLE VARCHAR(200),STATUSCODE INTEGER,CONTENTLENGTH BIGINT,RESPONSE VARCHAR(20000),REALIP VARCHAR(200));";
//		String sql2 = "CREATE TABLE PUBLIC.webfinderplus(ADDRESS VARCHAR(100),SSL BOOLEAN,SERVER VARCHAR(200),TITLE VARCHAR(200),STATUSCODE INTEGER,CONTENTLENGTH BIGINT,RESPONSE VARCHAR(20000));";
        Connection conn = DbUtils.getConnection();
        try {
            conn.createStatement().execute(sql1);
            conn.createStatement().execute(sql2);
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        // init webview
        id_webview = new WebView();
        id_browserpane.getChildren().add(id_webview);
        AnchorPane.setLeftAnchor(id_webview, 0.0);
        AnchorPane.setRightAnchor(id_webview, 0.0);
        AnchorPane.setTopAnchor(id_webview, 0.0);
        AnchorPane.setBottomAnchor(id_webview, 0.0);

        WebEngine eng = id_webview.getEngine();

        eng.locationProperty().addListener(new ChangeListener<String>() {
            @Override
            public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                id_url.setText(newValue);
            }
        });

    }

    @FXML
    private void newscan(ActionEvent event) {

        final Stage stage = new Stage();
        stage.initModality(Modality.APPLICATION_MODAL);

        BorderPane borderPane = new BorderPane();
        Scene scene = new Scene(borderPane, 900, 500);
        stage.setScene(scene);
        stage.setTitle("New Scan");
        stage.sizeToScene();

        borderPane.setPadding(new Insets(2, 2, 2, 2));

        borderPane.autosize();

        HBox hboxTop = new HBox();
        hboxTop.setPadding(new Insets(2, 2, 2, 2));
        hboxTop.setSpacing(3);

        Label lable = new Label("Input Ip List \t\t");
        CheckBox checkBox = new CheckBox("ip:port");

        hboxTop.getChildren().add(lable);
        hboxTop.getChildren().add(checkBox);

        TextArea textArea = new TextArea(null);
        textArea.setPrefWidth(790);
        textArea.setPrefHeight(340);
        textArea.setMaxWidth(-1);
        textArea.setPromptText("192.168.1.1\r\n" + "192.168.1.1/24\r\n" + "192.168.1-20\r\n");

        HBox hboxBottom = new HBox();
        hboxBottom.setPadding(new Insets(3, 3, 3, 3));
        hboxBottom.setSpacing(3);

        Button buttonStart = new Button("start");
        Button buttonCancel = new Button("cancel");

        ObservableList<String> ports = FXCollections.observableArrayList("1-65535", "Common ports");
        ComboBox<String> portsInput = new ComboBox<String>();
        portsInput.setItems(ports);
        portsInput.setEditable(true);
        portsInput.setPromptText("Input Ports");
        portsInput.setPrefWidth(600);
        HBox.setHgrow(portsInput, Priority.ALWAYS);

        ObservableList<Integer> threads = FXCollections.observableArrayList(1, 5, 10, 20, 30, 50, 80, 100, 150, 200,
                300, 500, 800, 1000);
        ComboBox<Integer> threadsInput = new ComboBox<Integer>();
        threadsInput.setItems(threads);
        threadsInput.setEditable(false);
        threadsInput.setPromptText("threads");

        ObservableList<Integer> timeput = FXCollections.observableArrayList(800, 1000, 1500, 2000, 3000, 5000);
        ComboBox<Integer> timeputInput = new ComboBox<Integer>();
        timeputInput.setItems(timeput);
        timeputInput.setEditable(false);
        timeputInput.setPromptText("timeout(ms)");

        hboxBottom.getChildren().addAll(portsInput, timeputInput, threadsInput, buttonStart, buttonCancel);

        borderPane.setTop(hboxTop);
        borderPane.setCenter(textArea);
        borderPane.setBottom(hboxBottom);

        checkBox.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                if (checkBox.isSelected()) {
                    portsInput.setDisable(true);
                    textArea.setPromptText("192.168.1.1:80\r\n" + "192.168.1.1:443\r\n" + "192.168.1.2:8080\r\n");
                } else {
                    portsInput.setDisable(false);
                    textArea.setPromptText("192.168.1.1\r\n" + "192.168.1.1/24\r\n" + "192.168.1.1-20\r\n");

                }
            }
        });

        // rootGroup.getChildren().add(borderPane);
        buttonStart.setOnAction(new EventHandler<ActionEvent>() {

            public void handle(ActionEvent event) {

                // ip:port mode
                if (checkBox.isSelected()) {
                    String strIps = textArea.getText();
                    LinkedList<String> ips = new LinkedList<>();

                    String[] ipArray = strIps.split("\n");

                    for (String ipPortStr : ipArray) {
                        if (!ips.contains(ipPortStr.trim())) {
                            ips.add(ipPortStr.trim());
                        }
                    }

                    Integer threads = threadsInput.getValue();
                    if (threads == null) {
                        threads = 100;
                    }
                    if (threadPool == null) {
                        threadPool = Executors.newFixedThreadPool(threads);
                    }

                    Integer to = timeputInput.getValue();
                    if (to == null) {
                        to = 3000;
                    }
                    taskCount++;

                    ScanTaskIpPort scanTask = new ScanTaskIpPort(ips, null, treeItem, threadPool, taskCount,
                            id_tableview, to, id_status, id_autodeleteempty);
                    taskList.add(scanTask);
                    new Thread(scanTask).start();

                    id_status.setText("scanning...");
                    stage.close();

                    Timer timer = new Timer("timer");
                    TimerTask timerTask = new TimerTask() {

                        @Override
                        public void run() {
                            ThreadPoolExecutor tpf = (ThreadPoolExecutor) threadPool;
                            Integer count = tpf.getQueue().size();
                            System.out.println(taskCount);
                            if (taskCount == 0 && count == 0) {
                                timer.cancel();
                                Platform.runLater(new Runnable() {
                                    @Override
                                    public void run() {
                                        id_status.setText("complete");
                                    }
                                });
                            }
                        }
                    };
                    timer.schedule(timerTask, 0, 3000);


                } else {
                    // ip list mode
                    String strIps = textArea.getText();

                    LinkedList<String> ips = new LinkedList<String>();
                    if (strIps != null) {
                        try {
                            ips = IpUtils.stringToIps(strIps);
                        } catch (UnknownHostException e) {
                            e.printStackTrace();
                        }
                    }

                    String strPorts = portsInput.getEditor().getText();
                    if (strPorts.equals("1-65535")) {
                        strPorts = "1-65535";
                    } else if (strPorts.equals("Common ports")) {

                        strPorts = "9043,9060,8080,80,443,5560,5500,7001,7002,4848,9000,10000,19000,1900,10080,5631,5632,4899,5800,5900,9090,2003,800,8000,9000,8088,8098,9044,8081,7080,18000,51000,52000,5631,5632,8443,3000,85,8500,18080,8008,2900,3900,10001,5555,8009,55555,29003,21,22,23,3306,1433,1521,2601,2604,9494,9495,1910,6788,6789,1494,22345,20300,9200,8090,30088,51000,9443,51000,873,7161,11211,6379,27017,27018,5335,50030,50070";
                    } else if (strPorts.equals("")) {

                        strPorts = "9043,9060,8080,80,443,5560,5500,7001,7002,4848,9000,10000,19000,1900,10080,5631,5632,4899,5800,5900,9090,2003,800,8000,9000,8088,8098,9044,8081,7080,18000,51000,52000,5631,5632,8443,3000,85,8500,18080,8008,2900,3900,10001,5555,8009,55555,29003,21,22,23,3306,1433,1521,2601,2604,9494,9495,1910,6788,6789,1494,22345,20300,9200,8090,30088,51000,9443,51000,873,7161,11211,6379,27017,27018,5335,50030,50070";
                    }

                    LinkedList<Integer> ports = IpUtils.stringToPorts(strPorts);
                    Integer threads = threadsInput.getValue();
                    if (threads == null) {
                        threads = 100;
                    }
                    if (threadPool == null) {
                        threadPool = Executors.newFixedThreadPool(threads);
                    }

                    Integer to = timeputInput.getValue();
                    if (to == null) {
                        to = 3000;
                    }
                    taskCount++;

                    ScanTaskDefault scanTaskDefault = new ScanTaskDefault(ips, ports, treeItem, threadPool, taskCount,
                            id_tableview, to, id_status, id_autodeleteempty);
                    taskList.add(scanTaskDefault);
                    new Thread(scanTaskDefault).start();

                    id_status.setText("scanning...");
                    stage.close();

                    Timer timer = new Timer("timer");
                    TimerTask timerTask = new TimerTask() {

                        @Override
                        public void run() {
                            ThreadPoolExecutor tpf = (ThreadPoolExecutor) threadPool;
                            Integer count = tpf.getQueue().size();
                            System.out.println(taskCount);
                            if (taskCount == 0 && count == 0) {
                                timer.cancel();
                                Platform.runLater(new Runnable() {
                                    @Override
                                    public void run() {
                                        id_status.setText("complete");
                                    }
                                });
                            }
                        }
                    };
                    timer.schedule(timerTask, 0, 3000);


                }

            }
        });

        buttonCancel.setOnAction(new EventHandler<ActionEvent>() {

            public void handle(ActionEvent event) {
                stage.close();
            }
        });
        stage.centerOnScreen();
        stage.showAndWait();

    }


//	@FXML
//	private void newscan(ActionEvent event) {
//
//		final Stage stage = new Stage();
//		stage.initModality(Modality.APPLICATION_MODAL);
//
//		BorderPane borderPane = new BorderPane();
//		Scene scene = new Scene(borderPane, 1000, 500);
//		stage.setScene(scene);
//		stage.setTitle("�½�ɨ��");
//		stage.sizeToScene();
//
//		borderPane.setPadding(new Insets(3, 3, 3, 3));
//
//		borderPane.autosize();
//
//		HBox hboxTop = new HBox();
//		hboxTop.setPadding(new Insets(3, 3, 3, 3));
//		hboxTop.setSpacing(3);
//
//		Label lable = new Label("������IP��ַ��");
//		hboxTop.getChildren().add(lable);
//
//		TextArea textArea = new TextArea(null);
//		textArea.setPrefWidth(790);
//		textArea.setPrefHeight(340);
//		textArea.setMaxWidth(-1);
//		textArea.setPromptText("192.168.1.1\r\n" + "192.168.1.1/24\r\n" + "192.168.1-20\r\n" + "www.baidu.com/24\r\n");
//
//		HBox hboxBottom = new HBox();
//		hboxBottom.setAlignment(Pos.CENTER_LEFT);
//		hboxBottom.setPadding(new Insets(3, 3, 3, 3));
//		hboxBottom.setSpacing(3);
//
//		Button buttonStart = new Button("��ʼ");
//		Button buttonCancel = new Button("ȡ��");
//
//		ObservableList<String> ports = FXCollections.observableArrayList("ȫ�˿�", "�����˿�");
//		ComboBox<String> portsInput = new ComboBox<String>();
//		portsInput.setItems(ports);
//		portsInput.setEditable(true);
//		portsInput.setPromptText("����ɨ��Ķ˿�");
//		portsInput.setPrefWidth(600);
//		HBox.setHgrow(portsInput, Priority.ALWAYS);
//
//		ObservableList<Integer> threads = FXCollections.observableArrayList(1, 5, 10, 20, 30, 50, 80, 100, 150, 200,
//				300, 500, 800, 1000);
//		ComboBox<Integer> threadsInput = new ComboBox<Integer>();
//		threadsInput.setItems(threads);
//		threadsInput.setEditable(false);
//		threadsInput.setPromptText("�߳���");
//
//		ObservableList<Integer> timeput = FXCollections.observableArrayList(800, 1000, 1500, 2000, 3000, 5000);
//		ComboBox<Integer> timeputInput = new ComboBox<Integer>();
//		timeputInput.setItems(timeput);
//		timeputInput.setEditable(false);
//		timeputInput.setPromptText("��ʱ(����)");
//
//		CheckBox includecommonports = new CheckBox("�����˿�");
//		hboxBottom.getChildren().addAll(portsInput, includecommonports, timeputInput, threadsInput, buttonStart,
//				buttonCancel);
//
//		borderPane.setTop(hboxTop);
//		borderPane.setCenter(textArea);
//		borderPane.setBottom(hboxBottom);
//
//		// rootGroup.getChildren().add(borderPane);
//		buttonStart.setOnAction(new EventHandler<ActionEvent>() {
//
//			public void handle(ActionEvent event) {
//
//				String strIps = textArea.getText();
//
//				LinkedList<String> ips = new LinkedList<String>();
//				if (strIps != null) {
//					try {
//						ips = IpUtils.stringToIps(strIps);
//					} catch (UnknownHostException e) {
//						e.printStackTrace();
//					}
//				}
//
//				String commonports = "21,22,23,25,80,85,110,139,443,445,455,512,513,800,873,1099,1433,1494,1521,1900,1910,2003,2222,2601,2604,2900,3000,3128,3306,3311,3312,3389,3900,4100,4440,4848,4899,5050,5168,5335,5500,5555,5560,5631,5632,5800,5900,5901,6000,6001,6082,6379,6788,6789,7001,7002,7080,7161,7777,8000,8001,8008,8009,8012,8080,8081,8088,8089,8090,8098,8099,8161,8443,8500,8649,8888,9000,9001,9043,9044,9060,9090,9200,9443,9494,9495,9999,10000,10001,10080,11211,16010,18000,18080,19000,20300,22345,27017,27018,28017,29003,30088,50000,50030,50060,50070,51000,52000,55555";
//				String strPorts = portsInput.getEditor().getText();
//				if (strPorts.equals("ȫ�˿�")) {
//					strPorts = "1-65535";
//				} else if (strPorts.equals("�����˿�") || strPorts.equals("")) {
//					strPorts = commonports;
//				} else {
//					if (includecommonports.isSelected()) {
//						strPorts = strPorts + "," + commonports;
//					}
//				}
//
//				LinkedList<Integer> ports = IpUtils.stringToPorts(strPorts);
//				Integer threads = threadsInput.getValue();
//				if (threads == null) {
//					threads = 200;
//				}
//				if (threadPool == null) {
//					threadPool = Executors.newFixedThreadPool(threads);
//				}
//
//				Integer to = timeputInput.getValue();
//				if (to == null) {
//					to = 3000;
//				}
//				taskCount++;
//
//				ScanTaskIpPort scanTask = new ScanTaskIpPort(ips, null, treeItem, threadPool, taskCount,
//						id_tableview, to, id_status, id_autodeleteempty);
//
////				ScanTask scanTask = new ScanTask(ips, ports, treeItem, threadPool, taskCount,
////						id_tableview, to, id_status, id_autodeleteempty);
//				taskList.add(scanTask);
//				new Thread(scanTask).start();
//
//				id_status.setText("����ɨ��...");
//				stage.close();
//
//				Timer timer = new Timer("timer");
//				TimerTask timerTask = new TimerTask() {
//
//					@Override
//					public void run() {
//						ThreadPoolExecutor tpf = (ThreadPoolExecutor) threadPool;
//						Integer count = tpf.getQueue().size();
//						System.out.println(taskCount);
//						if (taskCount == 0 && count == 0) {
//							timer.cancel();
//							Platform.runLater(new Runnable() {
//								@Override
//								public void run() {
//									id_status.setText("�����");
//								}
//							});
//						}
//					}
//				};
//				timer.schedule(timerTask, 0, 3000);
//
//			}
//		});
//
//		buttonCancel.setOnAction(new EventHandler<ActionEvent>() {
//
//			public void handle(ActionEvent event) {
//				stage.close();
//			}
//		});
//		stage.centerOnScreen();
//		stage.showAndWait();
//
//	}

    @FXML
    private void stop(ActionEvent event) {
        id_status.setText("stopping...");
        for (ScanTask scanTask : taskList) {
            scanTask.setStop(true);
        }
        ThreadPoolExecutor tpf = (ThreadPoolExecutor) threadPool;

        if (tpf != null) {
            tpf.getQueue().clear();
        }

        id_status.setText("stopped");
    }


    @FXML
    private void shrink(ActionEvent event) {
        // �����������ڵ㣬������ͣ
        ArrayList<TreeItem<String>> items = new ArrayList<TreeItem<String>>();
        try {

            ObservableList<TreeItem<String>> childs = treeItem.getChildren();
            for (TreeItem<String> item : childs) {
                if (item.isLeaf()) {
                    items.add(item);
                }
            }

            for (TreeItem<String> i : items) {
                i.getParent().getChildren().remove(i);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @FXML
    private void openurl(ActionEvent event) {
        String url = id_url.getText();
        url = url.startsWith("http") ? url : "http://" + url;
        id_webview.getEngine().load(url);

    }

    @FXML
    private void clearnotepad(ActionEvent event) {
        id_notepad.clear();
    }

    @FXML
    private void help(ActionEvent event) {
        // ���������url����֧��windows
        // try {
        // Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler
        // http://www.jb51.net");
        // } catch (IOException e1) {
        // // TODO Auto-generated catch block
        // e1.printStackTrace();
        // }
        // ���������url
        if (java.awt.Desktop.isDesktopSupported()) {
            try {
                // ����һ��URIʵ��,ע�ⲻ��URL
                URI uri = URI.create("http://www.cnblogs.com/SEC-fsq/p/5610981.html");
                // ��ȡ��ǰϵͳ������չ
                java.awt.Desktop dp = java.awt.Desktop.getDesktop();
                // �ж�ϵͳ�����Ƿ�֧��Ҫִ�еĹ���
                if (dp.isSupported(java.awt.Desktop.Action.BROWSE)) {
                    // ��ȡϵͳĬ�������������
                    dp.browse(uri);
                }
            } catch (NullPointerException e) {
                // ��ΪuriΪ��ʱ�׳��쳣
            } catch (IOException e) {
                // ��Ϊ�޷���ȡϵͳĬ�������
            }
        }
    }

    @FXML
    private void treeviewClicked(MouseEvent event) {

        TreeItem<String> treeitem = id_treeview.getSelectionModel().getSelectedItem();
        if (treeitem == null) {
            return;
        }
        String address = treeitem.getValue();

        if(!address.equals("+")){
            id_webview.getEngine().load("http://" + address);
        }

        TreeItem<String> ti = id_treeview.getSelectionModel().getSelectedItem();
        if (ti == null) {
            return;
        }
        String url = ti.getValue();
        String sql;
        ResultSet rs = null;
        PreparedStatement presm = null;
        Connection conn = DbUtils.getConnection();

        try {
            if (url.equals("+")) {
                sql = "select * from PUBLIC.webfinderplus";
                presm = conn.prepareStatement(sql);
            } else if (ti.isLeaf()) {
                sql = "select * from PUBLIC.webfinderplus where ADDRESS=?";
                presm = conn.prepareStatement(sql);
                presm.setString(1, url);
            } else {
                sql = "select * from PUBLIC.webfinderplus where ADDRESS like ?";
                presm = conn.prepareStatement(sql);
                String str = url + "%";
                presm.setString(1, str);
            }

            rs = presm.executeQuery();
            id_tableview.getItems().clear();

            while (rs.next()) {
                Row x = new Row(rs.getString(1), rs.getBoolean(2), rs.getString(3), rs.getString(4), rs.getInt(5),
                        rs.getLong(6), rs.getString(7), rs.getString(8));

//				Row x = new Row(rs.getString(1), rs.getBoolean(2), rs.getString(3), rs.getString(4), rs.getInt(5),
//						rs.getLong(6), rs.getString(7));
                id_tableview.getItems().add(x);
                if (ti.isLeaf()) {
                    if (rs.getBoolean(2) == true) {
                        id_webview.getEngine().load("https://" + rs.getString(1));
                    } else {
                        id_webview.getEngine().load("http://" + rs.getString(1));
                    }
                }
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (rs != null) {
                    rs.close();
                }

                presm.close();
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        id_tableview.refresh();
    }

    // search���ܻ�û�м��ϣ���ΪĿǰ���浽���ݿ�����ݲ���������Ӧbody���ݡ�
    @FXML
    private void search(ActionEvent event) {
        String keyword = id_url.getText();
        String sql;
        ResultSet rs = null;
        PreparedStatement presm = null;
        Connection conn = DbUtils.getConnection();

        try {

            sql = "select * from PUBLIC.webfinderplus where RESPONSE like ?";
            presm = conn.prepareStatement(sql);
            String str = "%" + keyword + "%";
            presm.setString(1, str);
            rs = presm.executeQuery();
            id_tableview.getItems().clear();

            while (rs.next()) {
                Row x = new Row(rs.getString(1), rs.getBoolean(2), rs.getString(3), rs.getString(4), rs.getInt(5),
                        rs.getLong(6), rs.getString(7), rs.getString(8));

//				Row x = new Row(rs.getString(1), rs.getBoolean(2), rs.getString(3), rs.getString(4), rs.getInt(5),
//						rs.getLong(6), rs.getString(7));
                id_tableview.getItems().add(x);
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (rs != null) {
                    rs.close();
                }

                presm.close();
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        id_tableview.refresh();

    }

    @FXML
    private void tableviewClicked(MouseEvent event) {

        Row row = id_tableview.getSelectionModel().getSelectedItem();
        if (row == null) {
            return;
        }

        String banner = row.responseProperty().getValueSafe().replace("\\n", "\n");
        id_serverinfo.setText(banner);

        if (!banner.startsWith("HTTP")) {
            String address = row.addressProperty().getValue();
            id_url.setText("tcp://" + address);
            id_webview.getEngine().loadContent(banner);
            return;
        }

        Boolean isSSL = row.sslProperty().getValue();
        String address = row.addressProperty().getValue();
        String urlsuffix = id_urlsuffix.getText();
        String url;
        if (isSSL) {
            url = "https://" + address + "/" + urlsuffix;
        } else {
            url = "http://" + address + "/" + urlsuffix;
        }
        id_url.setText(url);
        id_webview.getEngine().load(url);
    }

    @FXML
    private void clear(ActionEvent event) {
        TreeItem<String> ti = id_treeview.getSelectionModel().getSelectedItem();
        if (ti == null) {
            return;
        }
        if (!ti.isLeaf()) {
            ti.getChildren().clear();
        }
    }

    @FXML
    private void expandALL(ActionEvent event) {

        treeItem.setExpanded(true);
        ObservableList<TreeItem<String>> childs = treeItem.getChildren();
        for (TreeItem<String> item : childs) {
            if (!item.isLeaf()) {
                item.setExpanded(true);
            }
        }
    }

    @FXML
    private void collapseALL(ActionEvent event) {
        treeItem.setExpanded(false);
        ObservableList<TreeItem<String>> childs = treeItem.getChildren();
        for (TreeItem<String> item : childs) {
            if (!item.isLeaf()) {
                item.setExpanded(false);
            }
        }
    }

    @FXML
    private void sendHp(ActionEvent event) {

        TreeItem<String> ti = id_treeview.getSelectionModel().getSelectedItem();
        if ((ti != null) && ti.isLeaf()) {
            String tiUrl = ti.getValue();
            id_notepad.appendText(tiUrl + "\r\n");
        }

    }

    @FXML
    private void sendHhp(ActionEvent event) {
        TreeItem<String> ti = id_treeview.getSelectionModel().getSelectedItem();
        if ((ti != null) && ti.isLeaf()) {
            String tiUrl = ti.getValue();
            id_notepad.appendText("http://" + tiUrl + "\r\n");
        }
    }

    @FXML
    private void sendH(ActionEvent event) {
        TreeItem<String> ti = id_treeview.getSelectionModel().getSelectedItem();
        if ((ti != null) && ti.isLeaf()) {
            String tiUrl = ti.getValue();
            id_notepad.appendText(tiUrl.split(":")[0] + "\r\n");
        }
    }

    @FXML
    private void sendAllH(ActionEvent event) {
        ObservableList<TreeItem<String>> childs = treeItem.getChildren();
        for (TreeItem<String> item : childs) {
            if (!item.isLeaf()) {
                id_notepad.appendText(item.getValue() + "\r\n");
            }
        }
    }

    @FXML
    private void sendAllHhp(ActionEvent event) {
        ObservableList<TreeItem<String>> childs = treeItem.getChildren();
        for (TreeItem<String> item : childs) {
            if (!item.isLeaf()) {
                ObservableList<TreeItem<String>> childst = item.getChildren();
                for (TreeItem<String> itemt : childst) {
                    if (itemt != null) {
                        String tiUrl = itemt.getValue();
                        id_notepad.appendText("http://" + tiUrl + "\r\n");
                    }
                }
            }
        }

    }

    @FXML
    private void sendAllHp(ActionEvent event) {
        ObservableList<TreeItem<String>> childs = treeItem.getChildren();
        for (TreeItem<String> item : childs) {
            if (!item.isLeaf()) {
                ObservableList<TreeItem<String>> childst = item.getChildren();
                for (TreeItem<String> itemt : childst) {
                    if (itemt != null) {
                        String tiUrl = itemt.getValue();
                        id_notepad.appendText(tiUrl + "\r\n");
                    }
                }

            }
        }

    }

    @FXML
    private void cleartableview(ActionEvent event) {
        id_tableview.getItems().clear();

    }

    @FXML
    private void openbrowser(ActionEvent event) {

        if (java.awt.Desktop.isDesktopSupported()) {

            Row row = id_tableview.getSelectionModel().getSelectedItem();
            if (row == null) {
                return;
            }
            BooleanProperty isssl = row.sslProperty();
            StringProperty address = row.addressProperty();
            String schema = isssl.getValue() ? "https://" : "http://";
            String urlsuffix = id_urlsuffix.getText();
            String url = schema + address.getValueSafe() + "/" + urlsuffix;
            try {
                // ����һ��URIʵ��,ע�ⲻ��URL
                URI uri = URI.create(url);
                // ��ȡ��ǰϵͳ������չ
                java.awt.Desktop dp = java.awt.Desktop.getDesktop();
                // �ж�ϵͳ�����Ƿ�֧��Ҫִ�еĹ���
                if (dp.isSupported(java.awt.Desktop.Action.BROWSE)) {
                    // ��ȡϵͳĬ�������������
                    dp.browse(uri);
                }
            } catch (IllegalArgumentException e) {
                // e.printStackTrace();
                try {
                    Class<URI> clazz = URI.class;
                    Field path = clazz.getDeclaredField("path");
                    Field schemeSpecificPart = clazz.getDeclaredField("schemeSpecificPart");
                    Field string = clazz.getDeclaredField("string");
                    path.setAccessible(true);
                    schemeSpecificPart.setAccessible(true);
                    string.setAccessible(true);

                    int i = url.indexOf("//");
                    String strSchemeSpecificPart = url.substring(i);

                    String s = strSchemeSpecificPart.substring(2);
                    int j = s.indexOf("/");
                    String strpath = s.substring(j);

                    String scheme = url.substring(0, i + 2);
                    String host = s.substring(0, j);
                    host = host.trim();
                    URI uri = URI.create(scheme + host);

                    path.set(uri, strpath);
                    schemeSpecificPart.set(uri, strSchemeSpecificPart);
                    string.set(uri, url);
                    java.awt.Desktop dp = java.awt.Desktop.getDesktop();
                    // �ж�ϵͳ�����Ƿ�֧��Ҫִ�еĹ���
                    if (dp.isSupported(java.awt.Desktop.Action.BROWSE)) {
                        // ��ȡϵͳĬ�������������
                        dp.browse(uri);
                    }

                } catch (Exception ee) {

                }

            } catch (NullPointerException e) {
                // ��ΪuriΪ��ʱ�׳��쳣
            } catch (IOException e) {
                // ��Ϊ�޷���ȡϵͳĬ�������
            }

        }
    }

    @FXML
    private void exporttxt(ActionEvent event) {
        FileChooser fileChooser = new FileChooser();
        // fileChooser.setTitle("");
        fileChooser.getExtensionFilters().addAll(new ExtensionFilter("Text Files", "*.txt"));
        File selectedFile = fileChooser.showSaveDialog(null);
        if (selectedFile != null) {
            FileWriter fw = null;

            try {
                fw = new FileWriter(selectedFile);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            BufferedWriter bw = new BufferedWriter(fw);
            ObservableList<Row> items = id_tableview.getItems();
            for (Row row : items) {
                try {
                    bw.write(row.addressProperty().getValueSafe() + "	" + row.sslProperty().getValue() + "	"
                            + row.serverProperty().getValueSafe() + "	" + row.titleProperty().getValueSafe() + "	"
                            + row.statuscodeProperty().getValue() + "	" + row.contentLengthProperty().getValue()
                            + "	" + row.responseProperty().getValueSafe().replace("\n", "\\n").replace("\r", "\\r"));
                    bw.write("\r\n");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            try {
                bw.close();
                fw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

    }

    @FXML
    private void sendhttp(ActionEvent event) {
        ObservableList<Row> items = id_tableview.getItems();
        StringBuilder sb = new StringBuilder();
        for (Row row : items) {
            if (row.responseProperty().getValueSafe().startsWith("HTTP/1.") && !row.sslProperty().getValue())
                sb.append("http://" + row.addressProperty().getValueSafe() + "\n");
        }
        id_notepad.appendText(sb.toString());
    }

    @FXML
    private void sendhttps(ActionEvent event) {
        ObservableList<Row> items = id_tableview.getItems();
        StringBuilder sb = new StringBuilder();
        for (Row row : items) {
            if (row.responseProperty().getValueSafe().startsWith("HTTP/1") && row.sslProperty().getValue())
                sb.append("https://" + row.addressProperty().getValueSafe() + "\n");
        }
        id_notepad.appendText(sb.toString());
    }

    @FXML
    private void sendalladdress(ActionEvent event) {
        ObservableList<Row> items = id_tableview.getItems();
        StringBuilder sb = new StringBuilder();
        for (Row row : items) {
            sb.append(row.addressProperty().getValueSafe() + "\n");
        }
        id_notepad.appendText(sb.toString());
    }

    @FXML
    private void sendselectedaddress(ActionEvent event) {
        ObservableList<Row> items = id_tableview.getSelectionModel().getSelectedItems();
        StringBuilder sb = new StringBuilder();
        for (Row row : items) {
            sb.append(row.addressProperty().getValueSafe() + "\n");
        }
        id_notepad.appendText(sb.toString());
    }

    @FXML
    private void sendtotelnet(ActionEvent event) {
        Row item = id_tableview.getSelectionModel().getSelectedItem();
        if (item == null) {
            return;
        }
        String address = item.addressProperty().getValueSafe();
        String[] ipandport = address.split(":");
        try {
            // Map<String, String> envs = System.getenv();
            // Set<Entry<String, String>> entryset = envs.entrySet();
            // ArrayList<String> arraylist = new
            // ArrayList<String>(entryset.size());
            // for (Entry<String, String> entry : entryset) {
            // arraylist.add(entry.getKey() + "=" + entry.getValue());
            // }
            // String[] envps = new String[entryset.size()];
            // arraylist.toArray(envps);

            String cmd = "cmd /k start cmd /k telnet " + ipandport[0] + " " + ipandport[1];
            // String filename = "xmftelnettarget.bat";
            // FileWriter fw = new FileWriter(filename);
            // BufferedWriter bw = new BufferedWriter(fw);
            // bw.write(cmd);
            // bw.close();
            // cmd = "cmd /c start cmd /k " + filename;
            Runtime.getRuntime().exec(cmd);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @FXML
    private void cleardatabase(ActionEvent event) {
        Connection conn = DbUtils.getConnection();
        try {
            conn.createStatement().execute("delete from PUBLIC.webfinderplus");
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
                conn.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    }

    @FXML
    private void exportdata(ActionEvent event) {

        FileChooser fc = new FileChooser();
        fc.setTitle("export data");
        File file = fc.showSaveDialog(null);
        if (file == null) {
            return;
        }
        FileOutputStream fos = null;
        ObjectOutputStream oos = null;

        try {
            fos = new FileOutputStream(file);
            oos = new ObjectOutputStream(fos);
            ObservableList<Row> items = id_tableview.getItems();
            for (Row row : items) {
                RowSerializable rrs = new RowSerializable();
                rrs.setAddress(row.addressProperty().getValueSafe());
                rrs.setSsl(row.sslProperty().getValue());
                rrs.setServer(row.serverProperty().getValueSafe());
                rrs.setTitle(row.titleProperty().getValueSafe());
                rrs.setStatuscode(row.statuscodeProperty().getValue());
                rrs.setContentLength(row.contentLengthProperty().getValue());
                rrs.setResponse(row.responseProperty().getValueSafe());
                rrs.setRealIp(row.realIpProperty().getValueSafe());
                oos.writeObject(rrs);
            }
            oos.writeObject(null);

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {

            try {
                if (oos != null)
                    oos.close();
                if (fos != null)
                    fos.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                System.out.println("export exception!");
            }

        }
    }

    @FXML
    private void importdata(ActionEvent event) {
        FileChooser fc = new FileChooser();
        fc.setTitle("import data");
        File file = fc.showOpenDialog(null);
        if (file == null) {
            return;
        }
        FileInputStream fis = null;
        ObjectInputStream ois = null;
        try {
            fis = new FileInputStream(file);
            ois = new ObjectInputStream(fis);
            ObservableList<Row> items = id_tableview.getItems();
            items.clear();
            Row rr = null;
            RowSerializable rrs = null;
            while ((rrs = (RowSerializable) ois.readObject()) != null) {
                System.out.println(rrs);

                rr = new Row(rrs.getAddress(), rrs.getSsl(), rrs.getServer(), rrs.getTitle(), rrs.getStatuscode(),
                        rrs.getContentLength(), rrs.getResponse(), rrs.getRealIp());

//				rr = new Row(rrs.getAddress(), rrs.getSsl(), rrs.getServer(), rrs.getTitle(), rrs.getStatuscode(),
//						rrs.getContentLength(), rrs.getResponse());
                items.add(rr);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (ois != null)
                    ois.close();
                if (fis != null)
                    fis.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                System.out.println("import exception");
            }
        }
    }

    @FXML
    private void deleteitems(ActionEvent event) {
        ObservableList<Row> items = id_tableview.getSelectionModel().getSelectedItems();
        id_tableview.getItems().removeAll(items);
        id_tableview.refresh();
    }

    @FXML
    private void refresh(ActionEvent event) {
        id_tableview.refresh();
        id_treeview.refresh();
    }

}
